home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 2
/
Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso
/
Aminet
/
misc
/
amag
/
sh9301e.lha
/
Maxon-CPP-Demo
/
Source
/
FPlot
/
fclass.c
next >
Wrap
C/C++ Source or Header
|
1993-02-17
|
9KB
|
449 lines
/*
Funktionsplotter in Maxon C++
Function-Modul
Jens Gelhar 09.11.91
*/
#include <exec/types.h>
#include <intuition/intuition.h>
#include <stream.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <ctype.h>
#include "fclass.h"
// ******** Prototypen ********
struct Window *OpenWindow( struct NewWindow *newWindow );
void CloseWindow( struct Window *window );
void SetAPen( struct RastPort *rp, unsigned long pen );
void Move( struct RastPort *rp, long x, long y );
void Draw( struct RastPort *rp, long x, long y );
struct Message *WaitPort( struct MsgPort *port );
// ******** Pragmas ***********
#pragma amicall(SysBase, 384, WaitPort(a0))
#pragma amicall(GfxBase, 240, Move(a1,d0,d1))
#pragma amicall(GfxBase, 246, Draw(a1,d0,d1))
#pragma amicall(GfxBase, 342, SetAPen(a1,d0))
#pragma amicall(IntuitionBase, 204, OpenWindow(a0))
#pragma amicall(IntuitionBase, 72, CloseWindow(a0))
// ******** Zeichenroutine ********
// Windowdimensionen:
#define WW 640
#define WH 190
// Destruktoren:
Func::~Func() { } // Default: garnix
UnOpN::~UnOpN()
{ delete arg; }
BinOpN::~BinOpN()
{ delete l;
delete r;
}
// Konstruktoren:
double Func::Dummy;
KonstN::KonstN (double c)
{ Konst = c; }
UnOpN::UnOpN(UnOps op, Func *n):
oper(op), arg(n)
{ }
BinOpN::BinOpN(BinOps op, Func *ln, Func *rn):
oper(op), l(ln), r(rn)
{ }
// "Konstant"-Funktionen:
int Func::isconst (double &retval)
{ return 0; }
int KonstN::isconst (double &retval)
{ retval = Konst;
return 1;
}
// Ausgabe
#define EPANIC 26731
void KonstN::print(char*)
{
printf("%g", Konst);
}
void VarN::print(char*)
{ printf("x"); }
void ErrorN::print(char*)
{ printf("?"); }
void UnOpN::print(char* str)
{ switch(oper)
{ case Op_neg: printf("-"); break;
case Op_sqr: printf("sqr "); break;
case Op_sqrt: printf("sqrt "); break;
case Op_sin: printf("sin "); break;
case Op_cos: printf("cos "); break;
case Op_exp: printf("exp "); break;
case Op_ln: printf("ln "); break;
}
arg->print(str);
}
void BinOpN::print(char* str)
{ printf("(");
l->print(str);
switch (oper)
{ case Op_add: printf("+"); break;
case Op_sub: printf("-"); break;
case Op_mult:printf("*"); break;
case Op_div: printf("/"); break;
case Op_pot: printf("^"); break;
default: exit(EPANIC);
}
r->print(str);
printf(")");
}
// Auswertung
inline double sqr(double x)
{ return x*x; }
double intpotz(double base, int exp)
{ if (exp)
{ if (exp<0) return 1.0/intpotz(base,-exp)
else if (exp==1) return base;
else if (exp&1) return base*sqr(intpotz(base, exp/2));
else return sqr(intpotz(base, exp/2));
}
else return 1;
}
double UnOpN::eval (double x)
{
double y = arg->eval(x);
switch(oper)
{ case Op_neg: return -y;
case Op_sqr: return y*y;
case Op_sqrt: return sqrt(y);
case Op_sin: return sin(y);
case Op_cos: return cos(y);
case Op_exp: return exp(y);
case Op_ln: return log(y);
default: exit(EPANIC);
}
}
double BinOpN::eval (double x)
{ double lv = l->eval(x), rv = r->eval(x);
switch(oper)
{ case Op_add: return lv+rv;
case Op_sub: return lv-rv;
case Op_mult: return lv*rv;
case Op_div: return lv/rv;
case Op_pot: if (r->isconst() && floor(rv)==rv)
return intpotz(lv, int(rv))
else if (lv > 0) return exp(rv*log(lv));
return 0;
default: exit(EPANIC);
}
}
// ******** Parsing ********
#define EULER 2.7182818284
#define PI 3.141592653589
char *cp; // Zeiger auf String
char c; // gescanntes Zeichen
short ErrFlag; // Fehler aufgetreten?
char Get()
{ while ((c = *cp) == ' ')
cp++;
if(c) cp++;
return c;
}
Func *Fehler()
{ if (!ErrFlag)
{ cout << "\nError.\n";
ErrFlag = 1;
}
return new ErrorN;
}
Func *Expression();
Func *Term();
Func *Potenz();
Func *Factor()
{ while (c=='+') Get();
if (c=='x' || c=='X')
{ Get();
return new VarN;
}
else if (c >= '0' && c <= '9')
{
int i = 0;
enum {max = 80};
char numstr[max+1];
while (isdigit(c) && i<max)
{ numstr[i++] = c; Get(); }
if (c=='.')
{ numstr[i++] = c; Get(); }
while (isdigit(c) && i<max)
{ numstr[i++] = c; Get(); }
if (tolower(c)=='e')
{ numstr[i++] = c; Get();
if (c=='+' || c=='-')
{ numstr[i++] = c; Get(); }
else
if (!isdigit(c))
return Fehler();
while (isdigit(c) && i<max)
{ numstr[i++] = c; Get(); }
}
numstr[i]=0;
return new KonstN(atof(numstr));
}
else
if (c=='(')
{ Get();
Func *np = Expression();
if (c==')')
Get();
else
delete Fehler();
return np;
}
else
if (c=='c')
{ if (Get()=='o' && Get() == 's')
{ Get(); return new UnOpN(Op_cos, Factor()); }
else
return Fehler();
}
else
if (c=='e')
{ if (Get()!='x')
return new KonstN(EULER);
else if (Get() == 'p')
{ Get(); return new UnOpN(Op_exp, Factor()); }
else
return Fehler();
}
else if (c=='l')
{ if (Get()=='n')
return Get(), new UnOpN(Op_ln, Factor());
else
return Fehler();
}
else if (c=='p')
{ if (Get()!='i')
return Fehler();
Get(); return new KonstN(PI);
}
else if (c=='s')
{ Get();
if (c=='i')
{ if (Get() != 'n') return Fehler();
Get();
return new UnOpN(Op_sin, Factor());
}
else if (c=='q')
{ if (Get() != 'r') return Fehler();
if (Get()=='t')
{ Get();
return new UnOpN(Op_sqrt, Factor());
}
else return new UnOpN(Op_sqr, Factor());
}
else
return Fehler();
}
// Default-Ergebnis:
return Fehler();
}
Func *Potenz()
{
Func *n1 = Factor();
while (c=='^')
{ Get();
Func *n2 = Factor();
n1 = new BinOpN(Op_pot, n1, n2);
}
return n1;
}
Func *Term()
{ Func *n1 = Potenz();
while (c=='*' || c=='/')
{ BinOps op = c=='*'? Op_mult : Op_div;
Get();
Func *n2 = Potenz();
n1 = new BinOpN(op, n1, n2);
}
return n1;
}
Func *Expression()
{
if (c=='-')
{ Get();
Func *np = Term();
return new UnOpN(Op_neg,np);
}
else
{ Func *n1 = Term();
while (c=='+' || c=='-')
{ BinOps op = c=='+'? Op_add : Op_sub;
Get();
Func *n2 = Term();
n1 = new BinOpN(op, n1, n2);
}
return n1;
}
}
Func *Parse(char *string)
{ cp = string;
ErrFlag = 0;
Get();
Func *expr = Expression();
if (c) delete Fehler();
if(ErrFlag)
{ delete expr; return 0; }
else
return expr;
}
#pragma break -
void plot(Func *f, double minx, double maxx, double miny, double maxy)
{
NewWindow mynewwin =
{ 0, 0, WW, WH+10, 2, 1, IDCMP_CLOSEWINDOW,
WFLG_ACTIVATE | WFLG_SIZEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET | WFLG_GIMMEZEROZERO,
NULL, NULL, " Plot ++ ", NULL, NULL, 100, 50, 640, 200, WBENCHSCREEN};
struct Window* mywin = OpenWindow( &mynewwin);
if (!mywin) exit(1);
RastPort *RP = ( RastPort *)mywin->RPort;
double XS = WW / (maxx-minx), YS = WH / (maxy-miny);
int X0 = int(-XS*minx), Y0 = int(-YS*miny);
SetAPen( ( RastPort *)mywin->RPort, 3);
if (miny < 0 && maxy > 0)
{ // y-Achse zeichnen:
Move(RP, 0, WH-Y0);
Draw(RP, WW, WH-Y0);
}
if (minx < 0 && maxx > 0)
{ // x-Achse zeichnen:
Move(RP, X0, 0);
Draw(RP, X0, WH);
}
SetAPen( ( RastPort *)mywin->RPort, 0);
Move( ( RastPort *)mywin->RPort, 0, 0);
for (int i=0; i<WW; i++)
{ double x = minx+i/XS, y = f->eval(x);
int yp = int(YS*y+Y0);
if (yp > -WH && yp < 2*WH) Draw(RP, i, WH-yp);
SetAPen(RP, 1);
}
WaitPort(mywin->UserPort);
CloseWindow(mywin);
}
#pragma break +
void main()
{
char input[100], buf[200];
cout << "\nPlot ++\nGeschrieben von Jens Gelhar mit Maxon C++\n\n";
cout << "Funktion: f(x) = "; cin.getline(input, 100);
Func *MyExp = Parse(input);
if (MyExp)
{ double minX, maxX, minY, maxY;
for(;;)
{ cout << "X-Bereich: von "; cin >> minX;
cout << " bis "; cin >> maxX;
if (minX < maxX) break;
cout << "Das Minimum muß kleiner als das Maximum sein.\n";
}
for(;;)
{ cout << "Y-Bereich: von "; cin >> minY;
cout << " bis "; cin >> maxY;
if (minY < maxY) break;
cout << "Das Minimum muß kleiner als das Maximum sein.\n";
}
cout << "\nFunktion: "; MyExp->print(buf); cout << "\n";
plot(MyExp, minX, maxX, minY, maxY);
delete MyExp;
}
else
cout << "Versuch's doch gleich noch mal!\n";
}